… plugin guide (objectui#7636)
`skills/objectui/guides/plugin-development.md` documented `inputType`, `min`,
`max`, `step` and `placeholder` as ordinary writable optionals on
`ComponentInput`. All five are ADR-0049 retirement tombstones on the real type:
`?: never` on the interface in `packages/types/src/base.ts` and a
`retirementTombstone()` named refusal on the Zod mirror in
`packages/types/src/zod/base.zod.ts`. The guide therefore taught a write that is
a `tsc` error at the authoring site and a named parse refusal at runtime.
This is the PUBLISHED skills tree — the guide is copied into users'
repositories — so the blast radius is outside this repo, which is exactly where
the tombstones' named refusal was bought to help.
The fence now records the tombstones as `?: never` and points at `description`
as the published remedy, matching the real declaration's own wording.
Verified against the real declarations rather than against the gate:
`check:skill-examples` is green on this fence both before and after, because
the snippet re-declares `ComponentInput` locally instead of importing it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KbJQ1y1J12nZxYzFWhP8Q3
Part of #7636 — this implements part 1 only, the half the
domain:uiPM ruling dispatched. Part 2 (the gate question) is measured and filed as its own card, #7646, per that same ruling.What was wrong
skills/objectui/guides/plugin-development.mddocumented five members ofComponentInputas ordinary writable optionals:All five are ADR-0049 retirement tombstones on the real type. The guide therefore taught a write that is a
tscerror at the authoring site and a named parse refusal at runtime. This is the published skills tree — the guide is copied into users' repositories — so the blast radius is outside this repo, which is exactly where the tombstones' named refusal was bought to help.The fence now records the tombstones as
?: neverand points atdescriptionas the published remedy, in the real declaration's own wording.pnpm check:skill-examplesis green on this fence before and after, and that is the point. The fence declares its own localtype ComponentInputalias instead of importing the published one, so the gate compiles a private copy and cannot compare it to the real declaration.Evidence 1 — proven against the real declarations, with lit controls
Two instruments, both run against the built package, both agreeing:
tsc, importing the realComponentInputand attempting each write. Run twice, once resolved to the publishedpackages/types/dist/base.d.tsand once topackages/types/src/base.ts— identical results:Zod,
ComponentInputSchema.safeParseper key — all five refused withcode=invalid_typeand the issuepathnaming the key, each carrying its own remedy string.Lit control (both instruments): 2 of 2 genuinely-writable keys read as writable.
advancedanddescriptioncompile clean and parse clean. A control reading zero would have meant a dark instrument and the readings would have been discarded.An earlier attempt at this instrument WAS dark — it resolved no module at all and reported all seven probes as failures. It was rebuilt with an explicit declaration path, and the
--listFilesoutput was checked to confirm which declaration was actually read.Evidence 2 — the two-arm control on the gate itself
Both arms had the mutation confirmed on disk by anchored grep counts, and were restored with
git checkout HEAD -- PATH, verified bygit diff HEADempty and blob hash identical to the HEAD blob.Semantic phase: 13 of 13 ts fence(s) judged, 0 failedname: numberwhere the real member isname: string; all five tombstones restored as writable; plus an invented memberfrobnicateon no type at allArm B is the finding: the gate judged the fence (it is inside the
13 of 13, not skipped) and passed a snippet wrong about every member it names. That falsification is what justifies #7646.inputType?: neverin place and addedinputType?: string. Predicted green; it went red —TS2300: Duplicate identifierplusTS2717. That is the gate correctly catching an internally invalid snippet, and it says nothing about drift. The arm was rebuilt as an internally consistent lie before it measured the intended thing.Gates
All run on this PR's head — re-derived for the actual diff, not just the dispatched list.
check:skill-examples13 of 13 ts fence(s) judged, 0 failed;Marked: 13 ts (floor 13), 70 json (floor 70)— floors unmovedcheck:doc-snippets452 of 452 block(s) judged, 0 failedcheck:skills-paths88/89 stated path(s) resolve across 20 guide file(s)check:skill-eval-tokensEvery must_contain token is taught by its own skill bundlecheck:doc-fencescheck:doc-typescheck:control-bytesscanned 6246 tracked text file(s)check:shell-escape-residuecheck:skill-examplesandcheck:doc-snippetseach first returned exit 2, PRECONDITION NOT MET. That is NOT MEASURED — not a pass and not a red. Both were re-run after building what each names via its own--build-filter, and the verdicts above are from those re-runs.Changeset: none owed, citing the gate's own verdict line —
No source or published contract of a released package changed in this range, so no changeset is owed(1 file changed, 0 of them published source).Line-count ratchet
Docs-only, net +7 lines, same number on both readings:
skills/objectui/guides/plugin-development.md.mdunderskills/)The +7 buys the tombstone block: what
?: nevermeans, that it is atscerror and a named Zod refusal, why the keys were never published (the serializer's six forwarded keys), and thedescriptionremedy. It also carries the one distinction a reader can get wrong in a costly direction — thatBaseSchema.placeholder, the node-level prop, is a different key and is unaffected. The old text was 4 lines of writable-optional declarations; nothing else was rewrapped or re-flowed to buy those lines.Clause-② determination
Clause-②: no — my own determination, and it agrees with the PM's. The diff is one markdown file in the published skills tree. No schema key moves, no export moves, no accept/reject behaviour moves: the
?: nevertombstones and theretirementTombstone()refusals already exist and already behave this way. This PR only stops the documentation from contradicting them.Landing route
skills/**is a governed surface — agent drafts, human merges. Opened as a draft, and it is not enqueued and should not be. Parking for a human is the expected outcome here, not a failure.Out of scope, filed not fixed
os:check-marked fences do, and 18 more sit undercontent/docs/wherecheck:doc-snippetsis opt-out rather than opt-in. Distinct from check-doc-snippet-types 的扫描面不含skills/—— agent 复制进用户仓的代码样例,没有任何 typechecker 编译过 #5465, where the scanner does not reach the file at all; here it reaches it and the local re-declaration defeats it.🤖 Generated with Claude Code
https://claude.ai/code/session_01KbJQ1y1J12nZxYzFWhP8Q3
Generated by Claude Code